#include "ServerSocket.h"
#include "SocketMessage.h"
#include "GMPingConnection.h"
#include "SendGameMessage.h"
#include "Timer.h"
#include "GMSyncTimer.h"
#include "GMClientAccepted.h"

#include <iostream>
#include <assert.h>
#include <algorithm>

ServerSocket::ServerSocket()
{

}

ServerSocket::~ServerSocket()
{
	//SDLNet_TCP_DelSocket(m_socketSet, m_socket);
	//SDLNet_TCP_Close(m_socket);
	//SDLNet_FreeSocketSet(m_socketSet);
}

bool ServerSocket::Open(int port)
{
	//std::cout << "port: " << port << std::endl;
	SDLNet_ResolveHost(&m_ip, INADDR_ANY, port);
	//return m_ip.host == INADDR_NONE;

	if (m_ip.host == INADDR_NONE)
	{
		std::cout << "failed to resolve host" << std::endl;
		return false;
	}
	
	m_socket = SDLNet_TCP_Open(&m_ip);
	if (!m_socket)
	{
		std::cout << "failed to create server socket on port: " << port << std::endl;
		return false;
	}	

	return true;
}

Socket* ServerSocket::Accept()
{
	//Socket* s;
	//TCPsocket socket;
	//while(!socket)
	//{
	//	socket = SDLNet_TCP_Accept(socket);
	//	SDL_Delay(1000);
	//}
	//s->SetSocket(socket);

	TCPsocket socket = nullptr;
	while(!socket)
	{
		socket = SDLNet_TCP_Accept(m_socket);

		TheTimer::Instance()->UpdateTime();

		static float checkTimer = 0.0f;
		checkTimer += TheTimer::Instance()->GetDt();
		if (checkTimer > 1.0f)
		{
			std::cout << ".";
			checkTimer = 0.0f;
		}
		
		//static float pingTimer = 0.0f;
		//pingTimer += TheTimer::Instance()->GetDt();
		////std::cout << "pingTimer: " << pingTimer << std::endl;
		//if (pingTimer >= 5.0f)
		//{
		//	std::cout << "checking" << std::endl;
		//	// check clients for ping
		//	CheckMaxPing();
		//	pingTimer = 0.0f;
		//}
	}
	std::cout << "got socket" << std::endl;
	
	return new Socket(socket);
}

void ServerSocket::AddClient(ClientSocket* c)
{
	// tell other clients another was added
	int numOfClients = m_clients.size();
	GMClientAccepted* gm = new GMClientAccepted();
	GMClientAccepted* gm2 = new GMClientAccepted();
	
	for (int i = 0; i != numOfClients; i++)
	{
		if (m_clients[i]->IsOpen())
		{
			// tell current clients there was an added player
			gm->SetID(c->GetID());
			SendGameMessage(*gm, m_clients[i]);
		}
		else
		{
			// kick off server
			m_clients.erase(std::find(m_clients.begin(), m_clients.end(), m_clients[i]));
		}
	}
	
	SDL_Delay(20);
	for (int i = 0; i != numOfClients; i++)
	{
		if (m_clients[i]->IsOpen())
		{	
			// tell the new client what other clients are connected
			gm2->SetID(m_clients[i]->GetID());
			SendGameMessage(*gm2, c);
		}
		else
		{
			// kick them off server
			m_clients.erase(std::find(m_clients.begin(), m_clients.end(), m_clients[i]));
		}
	}

	delete gm;
	delete gm2;
	m_clients.push_back(c);
}

void ServerSocket::CheckMaxPing()
{
	GMPingConnection* gm = new GMPingConnection();
	//GMSyncTimer* gm3 = new GMSyncTimer();
	int numOfClients = m_clients.size();
	for (int i = 0; i != numOfClients; i++)
	{
		if (m_clients[i]->IsOpen())
		{
			//SendGameMessage(*gm3, m_clients[i]);
			SendGameMessage(*gm, m_clients[i]);
			//SDL_Delay(10);
		}
		else
		{
			// kick them off server
			m_clients.erase(std::find(m_clients.begin(), m_clients.end(), m_clients[i]));
		}
	}
	delete gm;
}

bool ServerSocket::ReceiveS(SocketMessage* sm)
{
	for (int i = 0; i != m_clients.size(); i++)
	{
		assert(m_clients[i]->GetSocket());

		const int len = 2000;
		unsigned char msg[len];

		while(HasData())
		{
			int result = SDLNet_TCP_Recv(m_clients[i]->GetSocket(), msg, len);
			if (result <= 0)
			{
				std::cout << "waiting to receive message" << std::endl;
				return false;
			}
			else
			{
				sm->Append(msg, msg + result);
			}
		}
	}

	return true;
}

void ServerSocket::UpdateClientPositions()
{
	//
}

void ServerSocket::SetClientPosition(int id, const D3DXVECTOR3& pos)
{
	for (int i = 0; i != m_clients.size(); i++)
	{
		if (m_clients[i]->GetID() == id)
		{
			m_clients[i]->SetPos(pos);
		}
	}
}

ClientSocket& ServerSocket::GetClient(int id) const
{
	for (int i = 0; i != m_clients.size(); i++)
	{
		if (m_clients[i]->GetID() == id)
		{
			return *m_clients[i];
		}
	}
	std::cout << "ServerSocket::GetClient(): didn't find client sock!" << std::endl;
	return ClientSocket();
}

bool ServerSocket::SendGameMessageToAll(GameMessage& gm)
{
	for (int i = 0; i != m_clients.size(); i++)
	{
		if (m_clients[i]->IsOpen())
		{
			if (!SendGameMessage(gm, m_clients[i]))
			{
				return false;
			}
		}
		else
		{
			// kick them off server
			m_clients.erase(std::find(m_clients.begin(), m_clients.end(), m_clients[i]));
		}
	}
	return true;
}